package master.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.springframework.util.ClassUtils;

/**
 * 对象判等工具
 */
public class ObjectUtils {

	/**
	 * 判断两个对象是否相等
	 *
	 * @param obj1 Object
	 * @param obj2 Object
	 * @return boolean
	 */
	public static boolean equals(Object obj1, Object obj2) {
	    return (obj1 == null)?(obj2 == null):obj1.equals(obj2);
	}

	/**
	 * 比较两个对象
	 * @param obj1
	 * @param obj2
	 * @return 比较结果，如果相等，返回0；obj1&gt;obj2，返回&gt;0；否则，返回&lt;0
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static int compare(Object obj1, Object obj2){
		if (obj1 == obj2) {
			return 0;
		}
		if (obj1 == null || obj2 == null) {
			return (obj1==null)?-1:1;
		}
		if (obj1.equals(obj2)) {
			return 0;
		}
		if (obj1 instanceof Number && obj2 instanceof Number) {
			return compare((Number)obj1, (Number)obj2);
		}
		if (obj1 instanceof Comparable){
			return ((Comparable)obj1).compareTo(obj2);
		}
		else if(obj2 instanceof Comparable){
			return -((Comparable)obj2).compareTo(obj1);
		}
		else{
			String str1 = String.valueOf(obj1);
			String str2 = String.valueOf(obj2);
			return str1.compareTo(str2);
		}
	}
	
	/**
	 * 比较两个数值对象
	 * @param num1
	 * @param num2
	 * @return 比较结果，如果相等，返回0；obj1&gt;obj2，返回&gt;0；否则，返回&lt;0
	 */
	public static int compare(Number num1, Number num2){
		if (num1 == num2) {
			return 0;
		}
		if (num1 == null || num2 == null) {
			return (num1==null)?-1:1;
		}
		if (num1.equals(num2)) {
			return 0;
		}
		double delta = num1.doubleValue() - num2.doubleValue();
		if (delta == 0) {
			return 0;
		} else {
			return delta <0?-1:1;
		}
	}

	/**
	 * 判断两个数组是否对应元素均相等
	 * @param objArray1 Object[]
	 * @param objArray2 Object[]
	 * @return boolean
	 */
	public static boolean equals(Object[] objArray1, Object[] objArray2) {
	    return Arrays.equals(objArray1, objArray2);
	}

	/**
	 * 判断两个列表是否相等
	 * @param al1
	 * @param al2
	 * @return boolean
	 */
	public static boolean equals(List<?> al1, List<?> al2){
		if (al1==al2)
            return true;
        if (al1==null || al2==null)
            return false;

        int length = al1.size();
        if (al2.size() != length)
            return false;

        for (int i=0; i<length; i++) {
            Object o1 = al1.get(i);
            Object o2 = al2.get(i);
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }

        return true;
	}
	
	/**
	 * 通过比较两个列表指定位置的元素大小来区分两个列表的大小
	 * @param al1
	 * @param al2
	 * @param index
	 * @return 比较结果，如果相等，返回0；obj1&gt;obj2，返回&gt;0；否则，返回&lt;0
	 */
	public static int compare(List<?> al1, List<?> al2, int index[]) {
		for (int i = 0; i < index.length; i++) {
			int loc = index[i];
			Object v1 = al1.get(loc);
			Object v2 = al2.get(loc);
			
			int c = compare(v1, v2);
			if (c == 0) {
				continue;
			} else {
				return c;
			}
		}
		return 0;
	}
	
	/**
	 * 从输入流中反序列化得到对象
	 * @param in
	 * @return 反序列化得到的对象
	 * @throws Exception
	 */
	public static Object getObjectFromInputStream(InputStream in) throws Exception{
		if (in == null){
			return null;
		}
		ObjectInputStream objIn = null;
		try {
			objIn = new ObjectInputStream(new BufferedInputStream(in));
			return objIn.readObject();
		} finally {
			if (objIn != null) {
				try {
					objIn.close();
				} catch (IOException e1) {
				}
			}
		}
	}
	
	/**
	 * 将对象序列化成字节数组
	 * @param object
	 * @return 字节数组
	 * @throws IOException
	 */
	public static byte[] convertSerializable2Bytes(Serializable object) throws IOException{
		ObjectOutputStream objOut = null;
		try {
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			objOut = new ObjectOutputStream(new BufferedOutputStream(out));
			objOut.writeObject(object);
			objOut.flush();
			byte[] bs = out.toByteArray();
			return bs;
		} finally{
			if(objOut != null){
				objOut.close();
			}
		}
	}
	
	/**
	 * 将对象转换为指定类型的对象（只支持简单装换）
	 * @param value
	 * @param type
	 * @return
	 */
	public static Object convertValue(Object value, Class<?> type) throws IllegalArgumentException {
		if (ClassUtils.isAssignableValue(type, value)) {
			return value;
		}
		if (Number.class.isAssignableFrom(type) ||
				(type.isPrimitive() && !type.equals(boolean.class) && !type.equals(char.class))) {//数值型
			value = convert2Number(type, value);
		} else if (String.class.equals(type)) {//字符型
			value = value.toString();
		} else if (Date.class.isAssignableFrom(type)) {//日期型
			value = convert2Date(type, value);
		} else if (type.equals(Boolean.class) || type.equals(boolean.class)) {//布尔型
			value = convert2Boolean(value);
		} else {
			throw new IllegalArgumentException("Value can not be converted to type ( " + type.getName() + ")");
		}
		return value;
	}
	
	/**
	 * 将输入值转换为布尔类型
	 * @param value
	 * @return
	 */
	public static Object convert2Boolean(Object value) {
		//2008.7.16 适应Mysql某些版本不能正确处理BIT类型
		if (value instanceof Number) {
			value = Math.abs(((Number)value).doubleValue()) > 1.0E-6;
		} else if (value instanceof String) {
			value = Boolean.parseBoolean((String)value) || "1".equals((String)value) || "Y".equalsIgnoreCase((String)value) || "T".equalsIgnoreCase((String)value);
		} else {
			throw new IllegalArgumentException("无法处理的类型");//无法处理的类型
		}
		return value;
	}
	
	/**
	 * 将输入值转换为对应类型的数值
	 * @param type 具体数值类型
	 * @param value
	 * @return
	 */
	public static Object convert2Number(Class<?> type, Object value) throws IllegalArgumentException {
		if (value instanceof String){
			int dotIndex = ((String)value).indexOf('.');
			if (dotIndex >= 0) {//可能是个浮点数
				value = new Double((String)value);
			} else {
				value = new Long((String)value);
			}			
		} 
		if (value instanceof Number) {
			Number num = (Number)value;
			if (type.equals(Integer.class) || type.equals(int.class)) {
				value = new Integer(num.intValue());
			} else if (type.equals(Double.class) || type.equals(double.class)) {
				value = new Double(num.doubleValue());
			} else if (type.equals(Long.class) || type.equals(long.class)) {
				value = new Long(num.longValue());
			} else if (type.equals(BigDecimal.class)) {
				value = new BigDecimal(num.doubleValue());
			} else if (type.equals(Short.class) || type.equals(short.class)) {
				value = new Short(num.shortValue());
			} else if (type.equals(Float.class) || type.equals(float.class)) {
				value = new Float(num.floatValue());
			} else if (type.equals(Byte.class) || type.equals(byte.class)) {
				value = new Byte(num.byteValue());
			} else {
				throw new IllegalArgumentException("无法处理的类型");//无法处理的类型
			}
		} else {
			throw new IllegalArgumentException("无法处理的类型");//无法处理的类型
		}
		
		return value;
	}
	
	/**
	 * 将输入值转换为对应类型的日期
	 * @param type 具体日期类型
	 * @param value
	 * @return
	 */
	public static Object convert2Date(Class<?> type, Object value) throws IllegalArgumentException {
		if (value instanceof String){
			value = UtilDateConverter.parse((String)value);
		}
		if (value instanceof Date || value instanceof Number) {
			try {
				Constructor<?> constructor = type.getConstructor(long.class);
				long timeInMilis = 0;
				if (value instanceof Date) {
					timeInMilis = ((Date)value).getTime();				
				} else if (value instanceof Number) {
					timeInMilis = ((Number)value).longValue();
				}
				value = constructor.newInstance(timeInMilis);
			} catch (NoSuchMethodException e) {//找不到合适的构造方法
				value = null;
			} catch (InstantiationException e) {
				value = null;
			} catch (IllegalAccessException e) {
				value = null;
			} catch (InvocationTargetException e) {
				value = null;
			}
		}
		return value;
	}
	
	/**
	 * 判断某对象是否可以被迭代（为集合或数组）
	 * @see #getIterator(Object)
	 * @param value
	 * @return 可被迭代，返回true；否则为false
	 */
	public static boolean isIterable(Object value){
		return value != null && (value instanceof Collection<?> || value.getClass().isArray());
	}
	
	/**
	 * 得到某个对象（集合或数组）的迭代器
	 * @see #isIterable(Object)
	 * @param value
	 * @return 迭代器
	 */
	public static Iterator<?> getIterator(Object value){
		if (value instanceof Collection<?>) {
			return ((Collection<?>)value).iterator();
		} else if (value != null && value.getClass().isArray()){
			if (value.getClass().getComponentType().isPrimitive()) {//基本类型数组
				int length = Array.getLength(value);
				List<Object> list = new ArrayList<Object>(length);
				for (int i = 0; i < length; i++) {
					list.add(Array.get(value, i));
				}
				return list.iterator();
			} else {
				return Arrays.asList((Object[])value).iterator();
			}			
		} else {
			throw new IllegalArgumentException("对象不能被迭代！");
		}
	}
}